//
///** @file fourth.h
//    This file shows how to configure another tenacitas::async::handlers.
//    There are three types of events, one handler class, and the handler creator
//    is the same as the handler class  
//*/
//
///** @example fourth.h */
//
//
//#include <tenacitas_async/handlers.h>
//#include <tenacitas_async/event.h>
//
//
//#include <cstdint>
//#include <string>
//#include <tenacitas_async/handlers.h>
//#include <tenacitas_async/event.h>
//
//using namespace std;
//using namespace tenacitas;
//
//namespace tenacitas {
//    namespace async {
//        /** namepsace created for the second test of tenacitas::async */
//        namespace test_4 {
//
//            /** The type of events that will be handled */
//            typedef async::event1<6, int16_t> event_a;
//            typedef async::event2<7, char, float> event_b;
//            typedef async::event3<8, uint16_t, string, char> event_c;
//
//            /** In this example, the same handler class can handle 3 types of 
//                events */
//            template <typename t_logger>
//            class handler {
//            public:
//                typedef std::shared_ptr<handler> ptr_t;
//
//                typedef t_logger logger_t;
//
//                handler( )
//                    : m_mutex( ){}
//
//
//                static ptr_t instance( ) {
//                    if ( !m_instance ) {
//                        m_instance = ptr_t( new handler( ) );
//                    }
//                    return m_instance;
//                }
//
//                /** Initially creating 2 handlers */
//                template<typename t_handlers>
//                void first_creation( event_id && p_id,
//                                            t_handlers & p_handlers ) {
//
//                    switch ( p_id ) {
//                    case 6:
//                        first_creation_a( p_handlers );
//                        break;
//                        
//                    case 7:
//                        first_creation_b( p_handlers );
//                        break;
//
//                    case 8:
//                        first_creation_c( p_handlers );
//                        break;
//                    }
//                }
//
//                /** Aditionaly creating 1 more handler */
//                template<typename t_handlers>
//                bool additional_creation( event_id && p_id,
//                                                 t_handlers & p_handlers ) {
//                    bool l_rc = false;
//                    
//                    switch ( p_id ) {
//                    case 6:
//                        l_rc = additional_creation_a( p_handlers );
//                        break;
//                        
//                    case 7:
//                        l_rc = additional_creation_b( p_handlers );
//                        break;
//
//                    case 8:
//                        l_rc = additional_creation_c( p_handlers );
//                        break;
//                    }
//                    return l_rc;
//                    
//                }
//
//
//                /** Handling event a */
//                void operator( ) ( event_a::ptr_t p_event ) {
//
//                    boost::lock_guard<boost::mutex> l_lock(m_mutex);
//
//                    log_begin( logger_t );
//
//                    log_debug( logger_t ) << "handling event a";
//
//                    boost::this_thread::sleep(boost::posix_time::seconds(3));
//
//                    log_info( logger_t ) << "\t\tevent "
//                                         << event_a::id << " output: "
//                                         << *p_event; 
//        
//                    log_end( logger_t );
//
//                }
//
//                /** Handling event b */
//                void operator( ) ( event_b::ptr_t p_event ) {
//                    boost::lock_guard<boost::mutex> l_lock(m_mutex);
//
//                    log_begin( logger_t );
//
//                    log_debug( logger_t ) << "handling event b";
//
//                    boost::this_thread::sleep(boost::posix_time::seconds(2));
//
//                    log_info( logger_t ) << "\t\tevent "
//                                         << event_b::id << " output: "
//                                         << *p_event;
//        
//                    log_end( logger_t );
//
//                }
//
//                /** Handling event c */
//                void operator( ) ( event_c::ptr_t p_event ) {
//                    boost::lock_guard<boost::mutex> l_lock(m_mutex);
//
//                    log_begin( logger_t );
//
//                    log_debug( logger_t ) << "handling event c";
//
//                    boost::this_thread::sleep(boost::posix_time::seconds(5));
//
//                    log_info( logger_t ) << "\t\tevent "
//                                         << event_c::id << " output: "
//                                         << *p_event;
//
//                    log_end( logger_t );
//                }
//
//            private:
//                boost::mutex m_mutex;
//
//                /** First creating for event_a */
//                template<typename t_handlers>
//                void first_creation_a( t_handlers & p_handlers ) {
//                    for ( uint16_t l_counter = 0; l_counter < 2; ++l_counter ) {
//                        p_handlers.add( ptr_t( new handler( ) ) ); 
//                    }
//                }
//
//                /** Additional creation for event_a */
//                template<typename t_handlers>
//                bool additional_creation_a( t_handlers & p_handlers ) {
//                    p_handlers.add( ptr_t( new handler( ) ) ); 
//                    return true;
//                }
//
//
//                /** First creating for event_b */
//                template<typename t_handlers>
//                void first_creation_b( t_handlers & p_handlers ) {
//
//                    for ( uint16_t l_counter = 0; l_counter < 3; ++l_counter ) {
//                        p_handlers.add( ptr_t( new handler ( ) ) );
//                    }
//                }
//
//                /** Additional creation for event_b */
//                template<typename t_handlers>
//                 bool additional_creation_b( t_handlers & p_handlers ) {
//                    p_handlers.add( ptr_t( new handler( ) ) ); 
//                    p_handlers.add( ptr_t( new handler( ) ) ); 
//                    return true;
//                }
//
//
//                /** First creating for event_c */
//                template<typename t_handlers>
//                void first_creation_c( t_handlers & p_handlers ) {
//                    for ( uint16_t l_counter = 0; l_counter < 1; ++l_counter ) {
//                        p_handlers.add( ptr_t( new handler ( ) ) );
//                    }
//                }
//
//                /** Additional creation for event_c */
//                template<typename t_handlers>
//                bool additional_creation_c( t_handlers & p_handlers ) {
//                    return false;
//                }
//            private:
//                /** Single instance */
//                static ptr_t m_instance;
//            };
//
//            template <typename t_logger>
//            typename handler<t_logger>::ptr_t
//            handler<t_logger>::m_instance;
//            
//
//            /** Groups the types necessary for a tenacitas::async::handlers for
//                event_a 
//                
//                @tparam t_logger is left as a template, so that the same logger
//                can be used by many tests
//             */
//            //template <typename t_logger>
//            //class supplier_a {
//            //public:
//            //    /** Type for the logger */
//            //    typedef t_logger logger_t;
//
//            //    /** Type for the event */
//            //    typedef event_a event_t;
//
//            //    /** Type of the event handler */
//            //    typedef handler<logger_t> handler_t;
//
//            //    /** Type for the handler creator */
//            //    typedef handler<logger_t> handler_factory_t;
//            //};
//
//            ///** Groups the types necessary for a tenacitas::async::handlers for
//            //    event_b
//            //    
//            //    @tparam t_logger is left as a template, so that the same logger
//            //    can be used by many tests
//            // */
//            //template <typename t_logger>
//            //class supplier_b {
//            //public:
//            //    /** Type for the logger */
//            //    typedef t_logger logger_t;
//
//            //    /** Type for the event */
//            //    typedef event_b event_t;
//
//            //    /** Type of the event handler */
//            //    typedef handler<logger_t> handler_t;
//
//            //    /** Type for the handler creator */
//            //    typedef handler<t_logger> handler_factory_t;
//            //};
//            //
//            ///** Groups the types necessary for a tenacitas::async::handlers for
//            //    event_c
//            //    
//            //    @tparam t_logger is left as a template, so that the same logger
//            //    can be used by many tests
//            // */
//            //template <typename t_logger>
//            //class supplier_c {
//            //public:
//            //    /** Type for the logger */
//            //    typedef t_logger logger_t;
//
//            //    /** Type for the event */
//            //    typedef event_c event_t;
//
//            //    /** Type of the event handler */
//            //    typedef handler<logger_t> handler_t;
//
//            //    /** Type for the handler creator */
//            //    typedef handler<t_logger> handler_factory_t;
//            //};
//
//
//
//            /** Runs the test
//
//                @tparam t_logger is left as a template, so that the same logger
//                can be used by many tests
//            */
//            template <typename t_logger>
//            void run( ) {
//
//                /** Type for the logger */
//                typedef t_logger logger_t;
//
//                /** All events are handled by the same class of handler */
//                typedef handler<logger_t> handler_t;
//
//                /** Type for the handler creator */
//                typedef handler<logger_t> handler_factory_t;
//
//                typedef typename handler_factory_t::ptr_t handler_factory_ptr_t;
//
//
//                /** Types for event_a */
//                typedef event_a event_a_t;
//                typedef event_a_t::ptr_t event_a_ptr_t;
//
//                /** Asynchronously event a handlers */
//                typedef handlers<
//                    logger_t, 
//                    event_a_t, 
//                    handler_t, 
//                    handler_factory_t 
//                > handlers_a_t;
//
//                /** Types for event_b */
//                typedef event_b event_b_t;
//                typedef event_b_t::ptr_t event_b_ptr_t;
//
//                /** Asynchronously event b handlers */
//                typedef handlers<
//                    logger_t, 
//                    event_b_t, 
//                    handler_t, 
//                    handler_factory_t
//                > handlers_b_t;
//
//                /** Types for event_c */
//                typedef event_c event_c_t;
//                typedef event_c_t::ptr_t event_c_ptr_t;
//
//                /** Asynchronously event a handlers */
//                typedef handlers<
//                    logger_t, 
//                    event_c_t, 
//                    handler_t, 
//                    handler_factory_t
//                > handlers_c_t;
//                
//
//                // lets go!!
//                log_begin( logger_t );
//
//                
//                // we'll fire 25 events
//
//                // also keep in mind that each handler sleeps for 2 seconds
//                uint16_t l_num_events ( 26 );
//
//                // to format the string part of the event
//                stringstream l_stream;
//
//                // to count the events fired
//                uint16_t l_counter ( 0 );
//
//                char l_c = 'A';
//
//                float l_f = 0.0;
//                
//                handler_factory_ptr_t l_handler_factory( new handler_factory_t( ) );
//                handlers_a_t l_handlers_a( l_handler_factory );
//                handlers_b_t l_handlers_b( l_handler_factory );
//                handlers_c_t l_handlers_c( l_handler_factory );
//
//                while ( true ) {
//
//                    if ( l_counter == l_num_events ) {
//                        break;
//                    }
//                    
//                    // breathing...
//                    boost::this_thread::sleep(boost::posix_time::millisec(10));
//
//                    log_debug( logger_t ) << "event number " << l_counter;
//
//                    char l_c_aux = static_cast<char>( l_c + l_counter );
//                    
//
//                    // event a
//                    l_handlers_a.handle( event_a_ptr_t( new event_a_t ( l_counter ) ) );
//
//                    // event b
//                    l_handlers_b.handle( event_b_ptr_t( new event_b_t ( l_c_aux, l_f +
//                                                               l_counter ) ) );
//
//                    // event c
//
//                    // formating the string part of the event
//                    l_stream.str( "" );
//                    l_stream << "counter " << l_counter;
//                    
//                    // sending the event
//                    l_handlers_c.handle( event_c_ptr_t( new event_c_t ( l_counter,
//                                                               l_stream.str( ), 
//                                                               l_c_aux ) ) ); 
//
//                    ++l_counter;
//                }
//            }
//
//        }
//    }
//}
